home *** CD-ROM | disk | FTP | other *** search
/ InfoMagic Internet Tools 1993 July / Internet Tools.iso / RockRidge / security / xinetd / xinetd.2.0.6 / signals.c < prev    next >
Encoding:
C/C++ Source or Header  |  1993-01-22  |  11.1 KB  |  523 lines

  1. /*
  2.  * (c) Copyright 1992 by Panagiotis Tsirigotis
  3.  * All rights reserved.  The file named COPYRIGHT specifies the terms 
  4.  * and conditions for redistribution.
  5.  */
  6.  
  7. static char RCSid[] = "$Id: signals.c,v 5.3 1992/11/10 08:17:38 panos Exp $" ;
  8.  
  9. #include <sys/types.h>
  10. #include <sys/time.h>
  11. #include <signal.h>
  12. #include <syslog.h>
  13. #include <errno.h>
  14. #include <string.h>
  15.  
  16. #include "str.h"
  17.  
  18. #include "defs.h"
  19. #include "config.h"
  20. #include "state.h"
  21. #include "flags.h"
  22.  
  23. extern int errno ;
  24.  
  25. void msg() ;
  26.  
  27. void exit() ;
  28. time_t time() ;
  29.  
  30. #define SIGSET_NULL                            ((sigset_t *)0)
  31. #define SIGVEC_NULL                            ((struct sigvec *)0)
  32. #define SIGACTION_NULL                        ((struct sigaction *)0)
  33.  
  34. #ifdef NO_POSIX_SIGS
  35.  
  36. #ifdef NO_POSIX_TYPES
  37. typedef int sigset_t ;
  38.  
  39. struct sigaction
  40. {
  41.     void (*sa_handler)() ;
  42.     sigset_t sa_mask ;
  43.     int sa_flags ;
  44. } ;
  45. #endif
  46.  
  47. #ifdef NO_SIGVEC
  48. #define sigmask( sig )                        ( 1 << ( (sig) -1 ) )
  49. typedef int (*sighandler_type)() ;
  50. #define sigpause( x )
  51. #define sigsetmask( x )
  52. #endif
  53.  
  54.  
  55. #define sigsuspend( set )                    sigpause( *set )
  56. #define sigemptyset( set )                    (*set) = 0
  57. #define sigaddset( set, sig )                ( ( (*set) |= sigmask( sig ) ), 0 )
  58. #define sigismember( set, sig )            ( ( (*set) & sigmask( sig ) ) != 0 )
  59.  
  60.  
  61. /*
  62.  * Only works for SIG_SETMASK and SIGUNBLOCK. Also oset must be NULL.
  63.  */
  64. int sigprocmask( how, set, oset )
  65.     int how ;
  66.     sigset_t *set ;
  67.     sigset_t *oset ;
  68. {
  69.     if ( how == SIG_BLOCK || oset != NULL )
  70.     {
  71.         msg( LOG_ERR, "sigprocmask",
  72.                                     "Bad args: how = %d, oset = %p", how, oset ) ;
  73.         return( -1 ) ;
  74.     }
  75.  
  76.     if ( how == SIG_SETMASK )
  77.     {
  78.         (void) sigsetmask( *set ) ;
  79.         return( 0 ) ;
  80.     }
  81.  
  82.     if ( how == SIG_UNBLOCK )
  83.     {
  84.         int current_mask = sigblock( 0 ) ;
  85.  
  86.         (void) sigsetmask( current_mask & ~*set ) ;
  87.         return( 0 ) ;
  88.     }
  89.     /* NOTREACHED */
  90. }
  91.  
  92.  
  93. /*
  94.  * NOTE: This is not a complete imitation of sigaction; in particular it
  95.  *            expects that sap is never NULL and that osap is always NULL.
  96.  */
  97. int sigaction( sig, sap, osap )
  98.     int sig ;
  99.     struct sigaction *sap ;
  100.     struct sigaction *osap ;
  101. {
  102.     if ( sap == NULL || osap != NULL )
  103.     {
  104.         msg( LOG_ERR, "sigaction", "Bad args: sap = %p, osap = %p", sap, osap ) ;
  105.         return( -1 ) ;
  106.     }
  107.  
  108. #ifndef NO_SIGVEC
  109.     {
  110.         struct sigvec sv ;
  111.  
  112.         sv.sv_handler = sap->sa_handler ;
  113.         sv.sv_mask = sap->sa_mask ;
  114.         sv.sv_flags = sap->sa_flags ;
  115.  
  116.         return( sigvec( sig, &sv, SIGVEC_NULL ) ) ;
  117.     }
  118. #else        /* NO_SIGVEC */
  119.     {
  120.         sighandler_type new_handler ;
  121.  
  122.         new_handler = sa.sa_handler ;
  123.         return( signal( sig, new_handler ) ) ;
  124.     }
  125. #endif    /* ! NO_SIGVEC */
  126. }
  127.  
  128. #endif    /* NO_POSIX_SIGS */
  129.  
  130.  
  131. /*
  132.  * reset_sigs is the list of signals that we need to reset to SIG_DFL.
  133.  * Currently, these are the signals whose actions we set to SIG_IGN.
  134.  * In general, we should also include any signals that have a handler
  135.  * that does anything other than setting a flag. We need to do this
  136.  * in case such a signal occurs while a forked process is providing
  137.  * an internal service.
  138.  */
  139. static sigset_t reset_sigs ;
  140.  
  141. /*
  142.  * nsig is equal to the greatest signal number supported plus 1
  143.  */
  144. static int nsig ;
  145.  
  146. /*
  147.  * Install signal handlers for all signals that can be caught.
  148.  * This implies that no core dumps are generated by default.
  149.  */
  150. status_e signal_init()
  151. {
  152.     register int sig ;
  153.     status_e handle_signal() ;
  154.     char *sig_name() ;
  155.     char *func = "install_signal_handlers" ;
  156.  
  157.     sigemptyset( &reset_sigs ) ;
  158.  
  159.     for ( sig = 1 ;; sig++ )
  160.         if ( handle_signal( sig ) == FAILED )
  161.             if ( errno == EINVAL )
  162.             {
  163.                 nsig = sig ;
  164.                 break ;
  165.             }
  166.             else
  167.             {
  168.                 msg( LOG_CRIT, func,
  169.                     "Failed to install signal handler for signal %s: %m",
  170.                         sig_name( sig ) ) ;
  171.                 return( FAILED ) ;
  172.             }
  173.     return( OK ) ;
  174. }
  175.  
  176.  
  177. void signal_wait()
  178. {
  179.     sigset_t masked_sigs ;
  180.  
  181.     sigemptyset( &masked_sigs ) ;
  182.     (void) sigsuspend( &masked_sigs ) ;
  183. }
  184.  
  185.  
  186. PRIVATE status_e handle_signal( sig )
  187.     register int sig ;
  188. {
  189.     struct sigaction sa ;
  190.     void (*sig_handler)() ;
  191.     void my_handler() ;                /* for the signals we are interested in */
  192.     void general_handler() ;        /* for everything else                         */
  193.  
  194.     switch ( sig )
  195.     {
  196.         case RECONFIG_SOFT_SIG:
  197.         case RECONFIG_HARD_SIG:
  198.         case TERMINATION_SIG:
  199.         case STATE_DUMP_SIG:
  200.         case CONSISTENCY_CHECK_SIG:
  201.         case SERVER_EXIT_SIG:
  202.         case RETRY_SIG:
  203.         case QUIT_SIG:
  204.             sig_handler = my_handler ;
  205.             break ;
  206.  
  207.         case SIGTTIN:
  208.         case SIGTTOU:
  209.         case SIGTSTP:
  210.             if ( debug.on )
  211.                 return( OK ) ;
  212.             /* FALL THROUGH */
  213.              
  214.         /*
  215.          * We may receive a SIGPIPE when handling an internal stream 
  216.          * service and the other end closes the connection.
  217.          * We only care about internal services that don't require forking.
  218.          */
  219.         case SIGPIPE:
  220.             sig_handler = SIG_IGN ;
  221.             sigaddset( &reset_sigs, sig ) ;
  222.             break ;
  223.  
  224.         case SIGKILL:
  225.         case SIGSTOP:
  226.             return( OK ) ;            /* we can't catch these two */
  227.         
  228.         case SIGTRAP:
  229.             if ( debug.on )
  230.                 return( OK ) ;
  231.         
  232. #if defined( DEBUG) && !defined( DEBUG_SIGNALS )
  233.         case SIGSEGV:
  234.         case SIGBUS:
  235.             return( OK ) ;
  236. #endif
  237.  
  238.         default:
  239.             sig_handler = general_handler ;
  240.     }
  241.  
  242.     sa.sa_flags = 0 ;
  243.     sigemptyset( &sa.sa_mask ) ;
  244.     sa.sa_handler = sig_handler ;
  245.     return( ( sigaction( sig, &sa, SIGACTION_NULL ) == -1 ) ? FAILED : OK ) ;
  246. }
  247.  
  248.  
  249. #define MAX_SIGNAL_COUNT                    50
  250. #define MAX_INTERVAL_SIGNAL_COUNT        10
  251. #define SIGNAL_INTERVAL                        1        /* second */
  252.  
  253. /*
  254.  * This function handles SIGSEGV and SIGBUS.
  255.  * Emergency action is taken if a certain number (MAX_SIGNAL_COUNT) of 
  256.  * these signals is received over the lifetime of the program OR 
  257.  * if a certain number (MAX_INTERVAL_SIGNAL_COUNT) of these signals 
  258.  * is received within a certain time interval (SIGNAL_INTERVAL).
  259.  *
  260.  * The action depends on the type of the emergency:
  261.  *        Case 1: MAX_INTERVAL_SIGNAL_COUNT is exceeded
  262.  *            If a setjmp environment is available, do a longjmp, otherwise exit
  263.  *        Case 2: MAX_SIGNAL_COUNT is exceeded
  264.  *            Exit
  265.  *
  266.  * NOTE: We try to send a message to the log only once to avoid
  267.  *            looping in this function (in case there is a bug in msg())
  268.  */
  269. PRIVATE void bad_signal()
  270. {
  271.     static time_t interval_start ;
  272.     static int interval_signal_count ;
  273.     static int total_signal_count ;
  274.     time_t current_time ;
  275.     char *func = "bad_signal" ;
  276.  
  277.     total_signal_count++ ;
  278.     if ( total_signal_count == MAX_SIGNAL_COUNT )
  279.     {
  280.         msg( LOG_CRIT, func,
  281.                 "Received %d bad signals. Exiting...", total_signal_count ) ;
  282.         exit( 1 ) ;
  283.     }
  284.     else if ( total_signal_count > MAX_SIGNAL_COUNT )
  285.         _exit( 1 ) ;        /* in case of a problem in exit(3) */
  286.     
  287.     (void) time( ¤t_time ) ;
  288.  
  289.     if ( interval_signal_count > 0 &&
  290.                 current_time - interval_start <= SIGNAL_INTERVAL )
  291.     {
  292.         interval_signal_count++ ;
  293.         if ( interval_signal_count == MAX_INTERVAL_SIGNAL_COUNT )
  294.         {
  295.             if ( ps.rws.env_is_valid )
  296.             {
  297.                 interval_start = current_time ;
  298.                 interval_signal_count = 1 ;
  299.                 msg( LOG_ERR, func, "Resetting..." ) ;
  300.                 longjmp( ps.rws.env, 1 ) ;
  301.                 /* NOTREACHED */
  302.             }
  303.             msg( LOG_CRIT, func,
  304.                 "Received %d signals in %d seconds. Exiting...",
  305.                     interval_signal_count, SIGNAL_INTERVAL ) ;
  306.             exit( 1 ) ;
  307.         }
  308.         else if ( interval_signal_count > MAX_INTERVAL_SIGNAL_COUNT )
  309.             _exit( 1 ) ;            /* shouldn't happen */
  310.     }
  311.     else
  312.     {
  313.         interval_start = current_time ;
  314.         interval_signal_count = 1 ;
  315.     }
  316. }
  317.  
  318.  
  319. #if defined( sun ) && defined( sparc )
  320. #undef SP
  321.  
  322. #include <machine/reg.h>
  323. #include <machine/frame.h>
  324.  
  325. PRIVATE void stack_trace( scp )
  326.     struct sigcontext *scp ;
  327. {
  328.     struct frame *fp ;
  329.     struct rwindow *rwp ;
  330.     char tracebuf[ 1000 ] ;
  331.     int len = 0 ;
  332.     unsigned size = sizeof( tracebuf ) - 1 ;
  333.  
  334.     tracebuf[ size ] = NUL ;
  335.  
  336.     if ( scp->sc_wbcnt != 0 )
  337.         return ;
  338.     rwp = (struct rwindow *) scp->sc_sp ;
  339.     len = strx_nprint( tracebuf, size, "%#x %#x", scp->sc_pc, rwp->rw_rtn ) ;
  340.     size -= len ;
  341.  
  342.     for ( fp = (struct frame *) rwp->rw_fp ; fp != NULL ; fp = fp->fr_savfp ) 
  343.     {
  344.         int cc ;
  345.  
  346.         cc = strx_nprint( &tracebuf[ len ], size,
  347.                                                 " %#x", (unsigned) fp->fr_savpc ) ;
  348.         len += cc ;
  349.         size -= cc ;
  350.         fp = fp->fr_savfp ;
  351.     }
  352.  
  353.     msg( LOG_CRIT, "stack_trace", "%s", tracebuf ) ;
  354. }
  355. #endif    /* sun && sparc */
  356.  
  357.  
  358.  
  359. PRIVATE char *sig_name( sig )
  360.     int sig ;
  361. {
  362.     static char signame_buf[ 30 ] ;
  363.  
  364. #ifndef NO_SIGLIST
  365.     extern char *sys_siglist[] ;
  366.  
  367.     if ( sig < NSIG )
  368.         return( strcpy( signame_buf, sys_siglist[ sig ] ) ) ;
  369. #endif
  370.     return( strx_sprint( signame_buf, sizeof( signame_buf ),
  371.                                 "signal=%d", sig ) ) ;
  372. }
  373.  
  374.  
  375. /*
  376.  * For SIGSEGV and SIGBUS we invoke the bad_signal() function (if this is 
  377.  * SunOS, we log the address where the problem occured).
  378.  *
  379.  * If we are not running under SunOS, we use the NO_SIGVEC flag to determine 
  380.  * if we have a struct sigcontext (since struct sigcontext is documented in 
  381.  * the sigvec man page).
  382.  *
  383.  * For other signals, we just log the fact that they occured.
  384.  * SIGINT is a special case since in debug.on mode, it will 
  385.  * cause termination.
  386.  */
  387.  
  388. #ifdef sun
  389.  
  390. PRIVATE void general_handler( sig, code, scp, addr )
  391.     int sig, code ;
  392.     struct sigcontext *scp;
  393.     char *addr;
  394. {
  395.     int pc = scp->sc_pc ;
  396.  
  397. #else        /* not a Sun */
  398.  
  399. #ifndef NO_SIGVEC
  400.  
  401. PRIVATE void general_handler( sig, code, scp )
  402.     int sig, code ;
  403.     struct sigcontext *scp;
  404. {
  405.     char *addr = NULL ;
  406.     int pc = scp->sc_pc ;
  407.  
  408. #else        /* defined( NO_SIGVEC ) */
  409.  
  410. PRIVATE void general_handler( sig )
  411.     int sig ;
  412. {
  413.     char *addr = NULL ;
  414.     int pc = 0 ;
  415.  
  416. #endif    /* ! NO_SIGVEC */
  417. #endif    /* sun */
  418.  
  419.     sigset_t badsigs ;
  420.     char *func = "general_handler" ;
  421.  
  422.     /*
  423.      * Do this here to catch problems like SIGSEGV in msg()
  424.      */
  425.     sigemptyset( &badsigs ) ;
  426.     sigaddset( &badsigs, sig ) ;
  427.     (void) sigprocmask( SIG_UNBLOCK, &badsigs, SIGSET_NULL ) ;
  428.  
  429.     switch ( sig )
  430.     {
  431.         case SIGBUS:
  432.         case SIGSEGV:
  433.             msg( LOG_CRIT, func,
  434.                     "(%d) Unexpected signal: %s, pc = %#x, address = %#x.",
  435.                         getpid(), sig_name( sig ), pc, addr ) ;
  436. #if defined( sun ) && defined( sparc )
  437.             stack_trace( scp ) ;
  438. #endif
  439.             bad_signal() ;
  440.             break ;
  441.         
  442.         default:
  443.             msg( LOG_NOTICE, func, "Unexpected signal %d: %s (addr=%#x)",
  444.                         sig, sig_name( sig ), addr ) ;
  445.             if ( debug.on && sig == SIGINT )
  446.                 exit( 1 ) ;
  447.     }
  448. }
  449.  
  450.  
  451. /*
  452.  * The job of this function is to set the flag that corresponds to the
  453.  * received signal. No other action is taken.
  454.  */
  455. PRIVATE void my_handler( sig )
  456.     int sig ;
  457. {
  458.     /*
  459.      * Signals are listed most-frequent-first
  460.      */
  461.     switch( sig )
  462.     {
  463.         case SERVER_EXIT_SIG:
  464.             M_SET( ps.flags, CHILD_FLAG ) ;
  465.             break ;
  466.         
  467.         case RETRY_SIG:
  468.             M_SET( ps.flags, RETRY_FLAG ) ;
  469.             break ;
  470.         
  471.         case RECONFIG_SOFT_SIG:
  472.             M_SET( ps.flags, SOFT_RECONFIG_FLAG ) ;
  473.             break ;
  474.         
  475.         case RECONFIG_HARD_SIG:
  476.             M_SET( ps.flags, HARD_RECONFIG_FLAG ) ;
  477.             break ;
  478.         
  479.         case TERMINATION_SIG:
  480.             M_SET( ps.flags, TERMINATE_FLAG ) ;
  481.             break ;
  482.         
  483.         case STATE_DUMP_SIG:
  484.             M_SET( ps.flags, DUMP_FLAG ) ;
  485.             break ;
  486.         
  487.         case CONSISTENCY_CHECK_SIG:
  488.             M_SET( ps.flags, CONSISTENCY_FLAG ) ;
  489.             break ;
  490.         
  491.         case QUIT_SIG:
  492.             M_SET( ps.flags, QUIT_FLAG ) ;
  493.             break ;
  494.     }
  495. }
  496.  
  497.  
  498. /*
  499.  * Reset all signals to default action. Reset the signal mask
  500.  *
  501.  * This function is invoked from a forked process. That is why we
  502.  * invoke _exit instead of exit (to avoid the possible stdio buffer flushes)
  503.  */
  504. void signal_default_state()
  505. {
  506.     register int sig ;
  507.     sigset_t empty ;
  508.  
  509.     for ( sig = 1 ; sig < nsig ; sig++ )
  510.         if ( sigismember( &reset_sigs, sig ) == 1 )
  511.             if ( (int) signal( sig, SIG_DFL ) == -1 )
  512.             {
  513.                 msg( LOG_ERR, "reset_signals",
  514.                     "signal(3) failed for signal %s: %m", sig_name( sig ) ) ;
  515.                 _exit( 1 ) ;
  516.             }
  517.         
  518.     sigemptyset( &empty ) ;
  519.     (void) sigprocmask( SIG_SETMASK, &empty, SIGSET_NULL ) ;
  520. }
  521.  
  522.  
  523.